﻿using Nop.Admin;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Media;
using Nop.Plugin.Widgets.Ribbon.Domain;
using Nop.Plugin.Widgets.Ribbon.Models;
using Nop.Plugin.Widgets.Ribbon.Services;
using Nop.Services.Catalog;
using Nop.Services.Directory;
using Nop.Services.Localization;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Vendors;
using Nop.Web.Framework;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Kendoui;
using Nop.Web.Framework.Mvc;
using Nop.Web.Models.Catalog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace Nop.Plugin.Widgets.Ribbon.Controllers
{
    public class WidgetsRibbonController : BasePluginController
    {
        #region Fields
        private readonly IRibbonService _ribbonService;
        private readonly IWorkContext _workContext;
        private readonly IStoreContext _storeContext;
        private readonly IStoreService _storeService;
        private readonly IPictureService _pictureService;
        
        private readonly ISpecificationAttributeService _specificationAttributeService;
        private readonly IPriceCalculationService _priceCalculationService;
        private readonly IPriceFormatter _priceFormatter;
        private readonly IWebHelper _webHelper;
        private readonly MediaSettings _mediaSettings;
        private readonly CatalogSettings _catalogSettings;
        private readonly ITaxService _taxService;
        private readonly ICurrencyService _currencyService;

        //private readonly ISettingService _settingService;
        private readonly ICacheManager _cacheManager;

        //private readonly ILanguageService _languageService;
        //private readonly ILocalizedEntityService _localizedEntityService;
        private readonly ILocalizationService _localizationService;
        private readonly IPermissionService _permissionService;
        private readonly ICategoryService _categoryService;
        private readonly IManufacturerService _manufacturerService;
        private readonly IVendorService _vendorService;
        private readonly IProductService _productService;
        #endregion

        #region crt
        public WidgetsRibbonController(IRibbonService ribbonService,
            IWorkContext workContext,
            IStoreContext storeContext,
            IStoreService storeService,
            IPictureService pictureService,
            //ISettingService settingService,
            ICacheManager cacheManager,
            //ILanguageService languageService,
            //ILocalizedEntityService localizedEntityService,
            ILocalizationService localizationService,
            IPermissionService permissionService,
            ICategoryService categoryService,
            IManufacturerService manufacturerService,
            IVendorService vendorService, IProductService productService,
            IPriceCalculationService priceCalculationService,
            IPriceFormatter priceFormatter,
            IWebHelper webHelper, 
            ISpecificationAttributeService specificationAttributeService,
            MediaSettings mediaSettings,
            CatalogSettings catalogSettings,
            ITaxService taxService, 
            ICurrencyService currencyService
            )
        {
            this._ribbonService = ribbonService;
            this._workContext = workContext;
            this._storeContext = storeContext;
            this._storeService = storeService;
            this._pictureService = pictureService;
            //this._settingService = settingService;
            this._cacheManager = cacheManager;
            //this._languageService = languageService;
            //this._localizedEntityService = localizedEntityService;
            this._localizationService = localizationService;
            this._permissionService = permissionService;
            this._categoryService = categoryService;
            this._manufacturerService = manufacturerService;
            this._vendorService = vendorService;
            this._productService = productService;
            this._priceCalculationService = priceCalculationService;
            this._priceFormatter = priceFormatter;
            this._webHelper = webHelper;
            this._specificationAttributeService = specificationAttributeService;
            this._mediaSettings = mediaSettings;
            this._catalogSettings = catalogSettings;
            this._taxService = taxService;
            this._currencyService = currencyService;
        }
        #endregion

        #region Utilities

        [NonAction]
        protected RibbonModel PrepareRibbonModel(RibbonObject ribbon)
        {

            var ribbonModel = new RibbonModel()
            {
                Id = ribbon.Id,
                Name = ribbon.Name,
                Text = ribbon.Text,
                RibbonClass  = ribbon.RibbonClass,
                TargetClass = ribbon.TargetClass,
                RibbonColor = ribbon.RibbonColor,
                Published = ribbon.Published,
            };

            return ribbonModel;
        }

        [NonAction]
        protected RibbonProductModel PrepareRibbonProductModelForList(RibbonProduct ribbonProduct)
        {
            var defaultProductPicture = _pictureService.GetPicturesByProductId(ribbonProduct.ProductId, 1).FirstOrDefault();
            var ribbonProductModel = new RibbonProductModel()
            {
                ProductId = ribbonProduct.ProductId,
                Id = ribbonProduct.Id,
                Published = ribbonProduct.Published,
                PictureThumbnailUrl = _pictureService.GetPictureUrl(defaultProductPicture, 75, true),
                ProductName = _productService.GetProductById(ribbonProduct.ProductId).Name,
            };
            return ribbonProductModel;
        }

        [NonAction]
        protected virtual IEnumerable<ProductOverviewModel> PrepareProductOverviewModels(IEnumerable<Product> products,
            bool preparePriceModel = true, bool preparePictureModel = true,
            int? productThumbPictureSize = null, bool prepareSpecificationAttributes = false,
            bool forceRedirectionAfterAddingToCart = false)
        {
            return this.PrepareProductOverviewModels(_workContext,
                _storeContext, _categoryService, _productService, _specificationAttributeService,
                _priceCalculationService, _priceFormatter, _permissionService,
                _localizationService, _taxService, _currencyService,
                _pictureService, _webHelper, _cacheManager,
                _catalogSettings, _mediaSettings, products,
                preparePriceModel, preparePictureModel,
                productThumbPictureSize, prepareSpecificationAttributes,
                forceRedirectionAfterAddingToCart);
        }

        #endregion

        #region Public

        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure()
        {
            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/Configure.cshtml");
        }

        [ChildActionOnly]
        public ActionResult PublicInfo(string widgetZone)
        {
            var model = new RibbonListModel();
            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/PublicInfo.cshtml", model);
        }
        #endregion
         
       #region Admin
        #region List

        public ActionResult Index()
        {
            return RedirectToAction("List");
        }

        public ActionResult List()
        {
            var model = new RibbonListModel();

            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/List.cshtml", model);
        }

        [HttpPost]
        public ActionResult List(DataSourceRequest command, RibbonListModel model)
        {
            var ribbons = _ribbonService.GetAllRibbons(model.SearchRibbonName,
                 command.Page - 1, command.PageSize);

            var tmp = new List<RibbonModel>();
            foreach (var ribbon in ribbons)
                tmp.Add(PrepareRibbonModel(ribbon));

            var tmp2 = tmp.PagedForCommand(command);
            var gridModel = new DataSourceResult
            {
                Data = tmp2,
                Total = tmp2.Count()
            };

            return new JsonResult
            {
                Data = gridModel
            };
        }

       #endregion

       #region Create / Edit / Delete

        public ActionResult Create()
        {
            var model = new RibbonModel();
            model.Published = true;
            model.Text = "Left Corner Wrap";
            model.TargetClass = "";
            model.RibbonClass = "wrap-ribbon left-corner";
            model.RibbonColor = "lblue";

            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/Create.cshtml", model);
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        public ActionResult Create(RibbonModel model, bool continueEditing)
        {
            if (ModelState.IsValid)
            {
                var ribbon = new RibbonObject()
                {
                    Id = model.Id,
                    Name = model.Name,
                    Text = model.Text,
                    RibbonClass  = model.RibbonClass,
                    RibbonColor  = model.RibbonColor,
                    TargetClass  = model.TargetClass ,
                    Published = model.Published,
                };
                _ribbonService.InsertRibbon(ribbon);

                SuccessNotification(_localizationService.GetResource("Plugins.Widgets.Ribbon.Added"));
                return continueEditing ? RedirectToAction("Edit", new { id = ribbon.Id }) : RedirectToAction("List");
            }

            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/Create.cshtml", model);
        }

        public ActionResult Edit(int id)
        {
            var ribbon = _ribbonService.GetRibbonById(id);
            if (ribbon == null)
                //No page found with the specified id
                return RedirectToAction("List");
            var model = PrepareRibbonModel(ribbon);

            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/Edit.cshtml", model);
        }

        [HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
        public ActionResult Edit(RibbonModel model, bool continueEditing)
        {
            var ribbon = _ribbonService.GetRibbonById(model.Id);
            if (ribbon == null)
                //No page found with the specified id
                return RedirectToAction("List");

            if (ModelState.IsValid)
            {
                ribbon.Name = model.Name;
                ribbon.Text = model.Text;
                ribbon.TargetClass = model.TargetClass;
                ribbon.RibbonClass = model.RibbonClass;
                ribbon.RibbonColor = model.RibbonColor;
                ribbon.Published = model.Published;

                _ribbonService.UpdateRibbon(ribbon);

                SuccessNotification(_localizationService.GetResource("Plugins.Widgets.Ribbon.Updated"));
                return continueEditing ? RedirectToAction("Edit", ribbon.Id) : RedirectToAction("List");
            }

            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/edit.cshtml", model);
        }

        [HttpPost]
        public ActionResult Delete(int id)
        {
            var ribbon = _ribbonService.GetRibbonById(id);
            if (ribbon == null)
                //No page found with the specified id
                return RedirectToAction("List");

            _ribbonService.DeleteRibbon(ribbon);

            SuccessNotification(_localizationService.GetResource("Plugins.Widgets.Ribbon.Deleted"));
            return RedirectToAction("List");
        }

       #endregion

        #region RibbonProduct

        [HttpPost]
        public ActionResult RibbonProductSelect(int ribbonId, DataSourceRequest command)
        {
            var ribbon = _ribbonService.GetRibbonById(ribbonId);
            if (ribbon == null)
                throw new ArgumentException("No ribbon found with the specified id", "ribbonId");

            var products = ribbon.RibbonProducts.OrderByDescending(rp => rp.Id).ToList();
            var gridModel = new DataSourceResult
            {
                Data = products.Select(PrepareRibbonProductModelForList),
                Total = products.Count
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        [HttpPost]
        public ActionResult RibbonProductDelete(int id)
        {
            var products = _ribbonService.GetRibbonProductById(id);
            if (products == null)
                throw new ArgumentException("No ribbon entity found with the specified id");

            _ribbonService.DeleteRibbonProduct(products);


            return Json(null);
        }

        [HttpPost]
        public ActionResult RibbonProductUpdate([Bind(Exclude = "ConfigurationRouteValues")] RibbonProductModel model)
        {
            var products = _ribbonService.GetRibbonProductById(model.Id);

            products.Published = model.Published;
            _ribbonService.UpdateRibbonProduct(products);

            return new NullJsonResult();
        }

        public ActionResult ProductAddPopup(int ribbonId)
        {
            var model = new AddRibbonProductModel();
            //categories
            model.AvailableCategories.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            var categories = _categoryService.GetAllCategories(showHidden: true);
            foreach (var c in categories)
                model.AvailableCategories.Add(new SelectListItem() { Text = c.GetFormattedBreadCrumb(categories), Value = c.Id.ToString() });

            //manufacturers
            model.AvailableManufacturers.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var m in _manufacturerService.GetAllManufacturers(showHidden: true))
                model.AvailableManufacturers.Add(new SelectListItem() { Text = m.Name, Value = m.Id.ToString() });

            //stores
            model.AvailableStores.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var s in _storeService.GetAllStores())
                model.AvailableStores.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString() });

            //vendors
            model.AvailableVendors.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });
            foreach (var v in _vendorService.GetAllVendors(showHidden: true))
                model.AvailableVendors.Add(new SelectListItem() { Text = v.Name, Value = v.Id.ToString() });

            //product types
            model.AvailableProductTypes = ProductType.SimpleProduct.ToSelectList(false).ToList();
            model.AvailableProductTypes.Insert(0, new SelectListItem() { Text = _localizationService.GetResource("Admin.Common.All"), Value = "0" });

            return View("~/Plugins/Widgets.Ribbon/Views/WidgetsRibbon/ProductAddPopup.cshtml", model);
        }

        [HttpPost]
        public ActionResult ProductAddPopupList(DataSourceRequest command, AddRibbonProductModel model)
        {
            var gridModel = new DataSourceResult();
            var products = _productService.SearchProducts(
                categoryIds: new List<int>() { model.SearchCategoryId },
                manufacturerId: model.SearchManufacturerId,
                storeId: model.SearchStoreId,
                vendorId: model.SearchVendorId,
                productType: model.SearchProductTypeId > 0 ? (ProductType?)model.SearchProductTypeId : null,
                keywords: model.SearchProductName,
                pageIndex: command.Page - 1,
                pageSize: command.PageSize,
                showHidden: true
                );
            gridModel.Data = products.Select(x => x.ToModel());
            gridModel.Total = products.TotalCount;

            return Json(gridModel);
        }

        [HttpPost]
        [FormValueRequired("save")]
        public ActionResult ProductAddPopup(string btnId, string formId, AddRibbonProductModel model)
        {
            if (model.SelectedProductIds != null)
            {
                foreach (int id in model.SelectedProductIds)
                {
                    var product = _productService.GetProductById(id);
                    if (product != null)
                    {
                        int pictureId = 0;
                        var pictureList = _productService.GetProductPicturesByProductId(product.Id);
                        if (pictureList != null && pictureList.Count > 0)
                            pictureId = pictureList.FirstOrDefault().PictureId;

                        _ribbonService.SaveRibbonProduct(product, model.RibbonId);
                    }
                }
            }

            ViewBag.RefreshPage = true;
            ViewBag.btnId = btnId;
            ViewBag.formId = formId;
            return View("~/Plugins/Widgets.Carousel/Views/WidgetsCarousel/ProductAddPopup.cshtml", model);
        }
        #endregion
        #endregion
    }
}